<?php
declare(strict_types=1);

namespace App\AdminApi\Module\Admin\Service;

use App\AdminApi\Module\Admin\Enums\MenuEnums;
use App\Common\Guard\AdminGuard;
use App\Common\Model\Admin\MenuModel;
use App\Sys;
use Zms\AdminElementPlus\FormCreate\Form;
use Zms\AdminElementPlus\FormCreate\FormItem;
use Zms\Basics\BasicsServe;
use Zms\Constants\Database;
use Zms\Exception\AppException;
use Zms\Guard\AuthUnit;
use Zms\Unit\Arr;

class MenuService extends BasicsServe
{

    /**
     * @return MenuModel::class
     */
    public static function model(): string
    {
        return MenuModel::class;
    }


    /**
     * 添加后台菜单
     * @param array $values
     * @return null|MenuModel
     * @throws AppException
     */
    public function created(array $values): MenuModel|false
    {
        if (intval($values['pid']) > 0) {
            /**
             * @var MenuModel $parent
             */
            $parent = $this->search(['id' => $values['pid']])->first();
            if (!$parent) {
                throw new AppException('上级菜单不存在,请刷新后重试');
            }
            $values['group'] = Arr::join(Arr::push($parent['group'], $values['pid']), ',');
            $values['level'] = $parent['level'] + 1;
        } else {
            $values['level'] = 0;
        }
        return parent::created($values);
    }


    /**
     * 删除菜单
     */
    public function remove($id)
    {
        return $this->search("(FIND_IN_SET('$id',`group`) OR `id`='$id')")->delete();
    }


    /**
     * 获取菜单全部数据
     * @param array $where
     * @return array
     */
    private function getMenuAll(array $where = []): array
    {
        $where['debug'] = Sys::develop() ? [1, 0] : 0;
        $all = $this->search($where)->orderByRaw('sort DESC,id DESC')->get()->toArray();
        foreach ($all as &$item) {
            $item['key'] = implode('-', [$item['id'], $item['pid']]);
            if ($item['node'] > 0) {
                $node = [];
                foreach ($item['node'] as $row) {
                    if (gettype($row) === 'string') {
                        $node[] = $row;
                    } elseif (gettype($row) === 'array') {
                        $node = array_merge($node, $row);
                    }
                }
                $item['node'] = $node;
            } else {
                $item['node'] = [];
            }
        }
        return $all;
    }


    /**
     * 获取菜单
     */
    public function getAdministerMenu(AdminGuard $guard): array
    {
        $authMenu = [];
        foreach ($this->getMenuAll() as $menu) {
            $count = count($menu['node'] ?? []);
            if ($count === 0 || ($count > 0 && $guard->isAuthorize($menu['node']))) {
                $authMenu[] = [
                    'id' => $menu['id'],
                    'pid' => $menu['pid'],
                    'path' => $menu['path'] ?? '',
                    'title' => $menu['name'],
                    'name' => (string)($menu['path'] ?: $menu['id']),
                    'meta' => ['id' => (string)$menu['id'],
                        'title' => $menu['name'],
                        'icon' => $menu['icon'],
                        'show' => $menu['is_nav']
                    ]
                ];
            }
        }
        return count($authMenu) > 0 ? Arr::getTree($authMenu) : [];
    }


    /**
     * 获取菜单显示数据
     */
    public function getMenuData(array $where = []): array
    {
        $menus = $this->getMenuAll($where);
        return Arr::getTree($menus);
    }


    /**
     * 获取表单数据
     * @return array
     */
    public function getFormData(): array
    {
        $data = $this->getMenuAll();
        $form = [];
        foreach ($data as $item) {
            $form[] = [
                'value' => (string)$item['id'], 'label' => $item['name'], 'pid' => (string)$item['pid']
            ];
        }
        return Arr::getTree($form, 'value');
    }


    /**
     * 创建菜单表单
     */
    public function createdMenuForm($pid = 0): Form
    {
        $rule[] = FormItem::Hidden('pid', $pid ?: 0);
        $rule[] = FormItem::Input('name', '菜单名称')->placeholder('后台菜单名称')->clearable(true)->maxlength(10)->required('请输入菜单名称');
        $rule[] = FormItem::Input('path', '菜单路由')->placeholder('前端菜单路由地址')->clearable(true)->maxlength(128);
        $rule[] = FormItem::Number('sort', '菜单排序')->placeholder('序号越大越靠前')->min(Database::INT_MIN)->max(Database::INT_MAX)->clearable(true);
        if ($pid) {
            $rule[] = FormItem::Hidden('icon', '');
            $rule[] = FormItem::Switchs('is_nav', '菜单显示', (string)MenuEnums::IS_NAV_YES)->col(24);
        } else {
            $rule[] = FormItem::IcoChoice('icon', '菜单图标')->col(12);
            $rule[] = FormItem::Switchs('is_nav', '菜单显示', (string)MenuEnums::IS_NAV_YES)->col(12);
        }
        $rule[] = FormItem::Cascader('node', '绑定权限')->options(AuthUnit::permissionsFormData('admin'))->valueKey('key')->labelKey('name')->clearable(true)->multiple(true);
        return Form::create('添加后台菜单')->setRules($rule)->setOptionFormInline(true);
    }


    /**
     * 编辑菜单表单
     */
    public function updatedMenuForm($id = 0): Form
    {
        /**
         * @var MenuModel $menu
         */
        $menu = $this->primaryByFirst($id);
        $rule[] = FormItem::Hidden('id', $id);
        $rule[] = FormItem::Input('name', '菜单名称', $menu->name)->placeholder('后台菜单名称')->clearable(true)->maxlength(10)->required('请输入菜单名称');
        $rule[] = FormItem::Input('path', '菜单路由', $menu->path)->placeholder('前端菜单路由地址')->clearable(true)->maxlength(128);
        $rule[] = FormItem::Number('sort', '菜单排序', $menu->sort)->placeholder('序号越大越靠前')->min(Database::INT_MIN)->max(Database::INT_MAX)->clearable(true);
        if ($menu->pid) {
            $rule[] = FormItem::Hidden('icon', '');
            $rule[] = FormItem::Switchs('is_nav', '菜单显示', (string)$menu->is_nav)->col(24);
        } else {
            $rule[] = FormItem::IcoChoice('icon', '菜单图标', $menu->icon)->col(12);
            $rule[] = FormItem::Switchs('is_nav', '菜单显示', (string)$menu->is_nav)->col(12);
        }
        $rule[] = FormItem::Cascader('node', '绑定权限', $menu->node)->options(AuthUnit::permissionsFormData('admin'))->valueKey('key')->labelKey('name')->clearable(true)->multiple(true);
        return Form::create('编辑后台菜单')->setRules($rule)->setOptionFormInline(true);
    }
}